// IO Monad 函子： 解决函子嵌套

const fp = require('lodash/fp')
const fs = require('fs')

class IO {
    static of (value){
        return new IO(function(){
            return value
        })
    }
    constructor (fn) {
        this._value = fn 
    }
    map(fn) {
        return new IO(fp.flowRight(fn, this._value))
    }
    
    // join方法是为了将map返回的 IO方法变扁
    join (){
        return this._value()
    }

    // 当IO返回的还是一个IO方法的时候使用
    flatMap(fn){
        return this.map(fn).join()
    }
}

// 模拟linux cat命令读取文件并打印出文件内容
const readFile = (filname) =>{
    return new IO(()=> fs.readFileSync(filname, 'utf-8') )
}

// x指的是读取文件后返回的文件内容
const print = (x)=>{
    return new IO(()=>{
        console.log(x)
        return x
    })
}

const r = readFile('package.json')
            .map(fp.toUpper)
            .flatMap(print)
            .join()
console.log(r)